package lk.icta.core.entity;

import lk.icta.common.entity.Child;
import lk.icta.common.entity.Contacts;
import lk.icta.common.entity.GNDivision;
import lk.icta.common.entity.Institute;
import lk.icta.user.entity.User;
import org.hibernate.annotations.IndexColumn;

import javax.persistence.*;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author Duminda Dharmakeerthi
 */
@Entity
@Table(schema = "ELAND_RAIL")
@NamedQueries({
        @NamedQuery(
                name = "findAllHolders",
                query = "SELECT h FROM Holder h"
        ),
        @NamedQuery(
                name = "getHolderByName",
                query = "SELECT h FROM Holder h WHERE h.name = :name"
        ),
        @NamedQuery(
                name = "getHolderByRegistrationNumber",
                query = "SELECT h FROM Holder h WHERE h.registrationNumberOrNIC = :registrationNumberOrNIC"
        )
})
public class Holder implements Serializable {
    /**
     * A system generated unique key
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    /**
     * Type of the Holder. 0-Institute, 1-Person, 2-Armed Forces and 3-Local Authority
     */
    @Column(nullable = false)
    private int holderType;

    /**
     * Name of holder
     */
    @Column(nullable = false)
    private String name;

    /**
     * Name of the head of the department
     */
    @Column(nullable = true)
    private String nameOfHead;

    /**
     * NIC Number of the holder
     */
    @Column(nullable = true)
    private String registrationNumberOrNIC;

    @Column(nullable = true)
    @Temporal(value = TemporalType.DATE)
    private Date dateOfBirth;

    //todo : rename to occupation
    @Column(nullable = true)
    private String designation;

    @OneToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
    @JoinColumn(nullable = true)
    private Contacts contacts;

    @OneToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
    @JoinColumn(nullable = true)
    private Contacts contactPerson;

    @Column(nullable = true)
    private String spouse;

    @OneToMany(cascade = {CascadeType.ALL})
    //@IndexColumn(name = "INDEX_COL")
    @JoinTable(schema = "ELAND_RAIL")
    private List<Child> children;

    @OneToOne
    @JoinColumn(nullable = true)
    private LocalAuthority localAuthority;

    @OneToOne
    @JoinColumn(nullable = true)
    private Institute institute;

    /**
     * Nationality of the person is Sri Lankan or not
     */
    @Column(nullable = true)
    private boolean nationality;

    /**
     * Gender 0 - male, 1 - female, 2 - unknown
     */
    @Column(nullable = true)
    private int gender;

    @ManyToOne
    @JoinColumn(nullable = true)
    private GNDivision gnDivision;

    @Column(nullable = true)
    private BigDecimal annualIncome;

    @OneToOne
    @JoinColumn
    private User slcUser;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getRegistrationNumberOrNIC() {
        return registrationNumberOrNIC;
    }

    public void setRegistrationNumberOrNIC(String registrationNumberOrNIC) {
        this.registrationNumberOrNIC = registrationNumberOrNIC;
    }

    public Date getDateOfBirth() {
        return dateOfBirth;
    }

    public void setDateOfBirth(Date dateOfBirth) {
        this.dateOfBirth = dateOfBirth;
    }

    public String getDesignation() {
        return designation;
    }

    public void setDesignation(String designation) {
        this.designation = designation;
    }

    public Contacts getContacts() {
        return contacts;
    }

    public void setContacts(Contacts contacts) {
        if (contacts != null) {
            this.contacts = contacts;
        }
    }

    public List<Child> getChildren() {
        return children;
    }

    public void setChildren(List<Child> children) {
       /* if (children != null) {
            List<Child> childList = new ArrayList<Child>();
            for (Child c : children) {
                if (c != null && c.getFullName() != null && !c.getFullName().isEmpty()) {
                    childList.add(c);
                }
            }
            this.children = childList;
        }*/
          this.children = children;
    }

    public String getSpouse() {
        return spouse;
    }

    public void setSpouse(String spouse) {
        this.spouse = spouse;
    }

    public String getNameOfHead() {
        return nameOfHead;
    }

    public void setNameOfHead(String nameOfHead) {
        this.nameOfHead = nameOfHead;
    }

    public int getGender() {
        return gender;
    }

    public void setGender(int gender) {
        this.gender = gender;
    }

    public LocalAuthority getLocalAuthority() {
        return localAuthority;
    }

    public void setLocalAuthority(LocalAuthority localAuthority) {
        this.localAuthority = localAuthority;
    }

    public int getHolderType() {
        return holderType;
    }

    public void setHolderType(int holderType) {
        this.holderType = holderType;
    }

    public Contacts getContactPerson() {
        return contactPerson;
    }

    public void setContactPerson(Contacts contactPerson) {
        if (contactPerson != null) {
            this.contactPerson = contactPerson;
        }
    }

    public boolean isNationality() {
        return nationality;
    }

    public void setNationality(boolean nationality) {
        this.nationality = nationality;
    }

    public GNDivision getGnDivision() {
        return gnDivision;
    }

    public void setGnDivision(GNDivision gnDivision) {
        this.gnDivision = gnDivision;
    }

    public BigDecimal getAnnualIncome() {
        return annualIncome;
    }

    public void setAnnualIncome(BigDecimal annualIncome) {
        this.annualIncome = annualIncome;
    }

    public User getSlcUser() {
        return slcUser;
    }

    public void setSlcUser(User slcUser) {
        this.slcUser = slcUser;
    }

    public Institute getInstitute() {
        return institute;
    }

    public void setInstitute(Institute institute) {
        this.institute = institute;
    }
}